package com.cnd.scm.orm;

import com.cnd.scm.jdbcprocessor.constant.CommandType;

import java.io.Serializable;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * @version V1.0
 * @InterfaceName: PhoenixRepository
 * @Description: PhoenixRepository 对应提供的服务接口
 * @author: 李启联
 * @date: 2020-05-19 10:17
 * @Copyright: Copyright (c) 2020
 */
public interface IPhoenixRepository<T extends Entity> {

    /**
     * 通用查询方法
     * @param parameter 查询参数对象
     * @return 返回单个实体对象
     * @throws Exception
     */
    Entity searchEntity(AccessParameter parameter) throws Exception;


    /**
     * 通用查询方法,根据传入的实体类型查询出单个实体对象
     * @param parameter 查询参数对象
     * @param type 实体类型
     * @return 返回单个实体对象
     * @throws Exception
     */
    Entity searchEntity(AccessParameter parameter, Type type) throws Exception;

    /**
     * 根据ID返回 Map<String,Object> 结构的对象数据
     * @param id 数据库主键对应的值
     * @return 数据库中对应存储的数据
     * @throws Exception
     */
    Map<String,Object> getMapById(String id) throws  Exception;

    /**
     * 通用的搜索方法，返回实体对象的集合。
     * @param parameter 查询参数对象
     * @return 查找到的实体对象集合
     * @throws Exception
     */
    EntityCollection searchEntityCollection(AccessParameter parameter) throws Exception;

    /**
     * 通用的搜索方法，根据传入的实体类型返回实体对象的集合。
     * @param parameter 查询参数对象
     * @param type 实体类型
     * @return 查找到的实体对象集合
     * @throws Exception
     */
    EntityCollection searchEntityCollection(AccessParameter parameter, Type type) throws Exception;

    /**
     * 通用的搜索方法，根据条件和实体类型返回实体对象的集合。
     * @param parameter 查询参数对象
     * @return 查找到的实体对象集合
     * @throws Exception
     */
    List<? extends Entity> searchEntityList(AccessParameter parameter) throws Exception;

    /**
     * 通用的搜索方法，根据条件和实体类型返回实体对象的集合。
     * @param parameter 查询参数对象
     * @param type 实体类型
     * @return 查找到的实体对象集合
     * @throws Exception
     */
    List<? extends Entity> searchEntityList(AccessParameter parameter, Type type) throws Exception;

    /**
     * 通用的搜索方法，返回实体对象的分页对象。
     * @param parameter 查询参数对象
     * @return 查找到的实体对应的分页对象
     * @throws Exception
     */
    <T> PageInfo<T> searchEntityPageInfo(AccessParameter parameter) throws Exception;

    /**
     * 通过sql查询语句或执行存储过程,返回对应实体集合 [支持递归]
     * @param commandType 执行类型[SQL语句或存储过程]
     * @param cmdText SQL语句或存储过程名称
     * @param objects 执行参数
     * @return  对应实体集合
     * @throws Exception
     */
    List<? extends Entity> searchEntityListBySQL(CommandType commandType, String cmdText, Object... objects) throws Exception;

    /**
     * 批量查询,通过一组ids批量查询到对应的实体集合列表
     * @param ids   主键列表
     * @return 实体集合列表
     * @throws Exception
     */
    List<? extends Entity> searchEntityListByIds(List<? extends Serializable> ids) throws Exception;

    /**
     * 删除实体对象的主方法（支持级联删除） 并提供事务处理机制
     * @param entity 实体对象
     * @return  删除成功返回true 并提交事务，否则返回false 回滚事务
     * @throws SQLException
     */
    boolean delete(Entity entity) throws SQLException;

    /**
     * 在数据库中级联删除对应的实体<BR/>
     * 通用的删除实体对象。此方法会先检测该实体对象中设置的级联删除对象，在删除该实体对象前先删除对应设置的级联对象
     * @param entity 实体对象
     * @return 删除成功返回true，否则返回false
     * @throws Exception
     */
    boolean deleteWithRecursive(Entity entity) throws Exception;

    /**
     * 删除单个实体对象 不考虑级联删除对象
     * @param entity 实体对象
     * @return  删除成功返回true，否则返回false
     * @throws Exception
     */
    boolean deleteForSingle(Entity entity) throws Exception;

    /**
     * 单纯的根据id的值从数据库中删除一个单一实体对象
     * @param idValue 实体对象ID 的值
     * @return 返回成功或失败
     * @throws Exception
     */
    boolean deleteByIdForSingle(Object idValue) throws Exception;

    /**
     *批量删除实体对象集合，支持递归删除
     * @param ids  实体对应的主键集合列表
     * @param recursive 是否递归删除
     * @return  返回成功或失败
     * @throws Exception
     */
    boolean deleteBatchByIds(List<? extends Serializable> ids, boolean recursive) throws Exception;

    /**
     * 新增加实体对象到数据库的主方法 提供事务处理 机制
     * @param entity 实体对象
     * @return  增加成功返回true 并提交事务，否则返回false 回滚事务
     * @throws SQLException
     */
    boolean insert(Entity entity) throws SQLException;

    /**
     * 在数据库中级联增加对应的实体
     * @param entity 实体对象
     * @return 增加成功返回true，否则返回false
     * @throws Exception
     */
    boolean insertWithRecursive(Entity entity) throws Exception;

    /**
     * 向数据库中新增单个实体对象数据
     * @param entity 实体对象
     * @return 新增成功返回 true 新增失败返回 false
     * @throws Exception
     */
    boolean insertForSingle(Entity entity) throws Exception;

    /**
     * 更新实体对象到数据库的主方法 <br/>(支持级联更新：需要在对应实体模型对象中标记级联更新实体对象 例： cascadeUpdateEntitys={A.class,B.class}) <br/>
     * 提供事务处理机制
     * @param entity 实体对象
     * @return  增加成功返回true 并提交事务，否则返回false 回滚事务
     * @throws SQLException
     */
    boolean update(Entity entity) throws SQLException;

    /**
     * 更新实体对象到数据库 提供事务处理机制<br/>
     * 选择性字段更新,只对值不为空的字段更新 (支持级联更新：需要在对应实体模型对象中标记级联更新实体对象 例： cascadeUpdateEntitys={A.class,B.class})
     * @param entity 实体对象
     * @return 增加成功返回true 并提交事务，否则返回false 回滚事务
     * @throws SQLException
     */
    boolean updateWithSelective(Entity entity) throws SQLException;

    /**
     * 在数据库中级联更新对应的实体 递归更新对应实体<br/> (支持级联更新：需要在对应实体模型对象中标记级联更新实体对象 例： cascadeUpdateEntitys={A.class,B.class})
     * 先更新主实体 后更新从实体
     * @param entity 实体对象
     * @return
     * @throws Exception
     */
    boolean updateWithRecursive(Entity entity) throws Exception;

    /**
     * 在数据库中级联更新对应的实体 递归更新对应实体 <br/> (支持级联更新：需要在对应实体模型对象中标记级联更新实体对象 例： cascadeUpdateEntitys={A.class,B.class})
     * 先更新主实体 后更新从实体
     * @param entity 实体对象
     * @param  isSelectiveUpdate  是否选择性字段更新（即：只更新指定不为空的字段）
     * @return 更新成功返回true，否则返回false
     * @throws Exception
     */
    boolean updateWithRecursive(Entity entity, boolean isSelectiveUpdate) throws Exception;

    /**
     * 更新单个实体对象到数据库中,不级联更新其他实体对象
     * @param  entity 实体对象
     * @param  isSelectiveUpdate  是否选择性字段更新（即：只更新指定不为空的字段）
     * @return 更新成功返回true，否则返回false
     * @throws Exception
     */
    boolean updateForSingle(Entity entity, boolean isSelectiveUpdate) throws Exception;

    /**
     * 初始化实体对象及其级联实体对象的主键字段为null值 (在复制新增这业务场景下运用普遍)
     * @param entity 实体对象
     * @throws Exception
     */
    void inItIdentityProperty(Entity entity)throws Exception;

    /**
     * 填充实体对象 如果实体对象内有定义其他实体对象的集合或单个实体属性 则会递归从数据库中取出对应的数据填充到对应的属性
     * 该方法用于从数据库中查询到数据后，把数据填充到实体对象
     *
     * @param map
     *            准备好的 已有的map对象 可以理解为DataRow
     * @param type
     *            欲填充的实体对象的类型
     * @param prefix
     *            列名的前缀
     * @return 返回填充好的实体
     * @throws Exception
     */
    Entity fillEntity(Map<String, Object> map, Type type, String prefix) throws Exception;

    /**
     * 通过实体对象的主键值返回该实体对象对应的Map对象
     *
     * @param type
     *            ：实体对象类型
     * @param obj
     *            ：实体对象identityProperty 的值
     * @return Map
     * @throws ClassNotFoundException
     * @throws Exception
     */
    Map<String, Object> searchEntityById(Type type, Object obj) throws Exception;

    Object getMappingValue(Type type, String targetFieldName, String keyFieldName, Object keyValue) throws Exception;
}